Skip to content

feat(firestore): support let stage#16030

Open
Linchin wants to merge 4 commits intogoogleapis:mainfrom
Linchin:fs-let
Open

feat(firestore): support let stage#16030
Linchin wants to merge 4 commits intogoogleapis:mainfrom
Linchin:fs-let

Conversation

@Linchin
Copy link
Contributor

@Linchin Linchin commented Mar 5, 2026

TODO:

  • verify docstring
  • add variable_field_reference

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request introduces the let pipeline stage to the Firestore client library, enabling users to define and compute variables within a pipeline. These variables can then be referenced in subsequent stages, significantly enhancing the flexibility and expressiveness of data processing pipelines by allowing intermediate calculations and named values.

Highlights

  • New 'let' Pipeline Stage: Introduced a new let pipeline stage that allows users to define and compute variables within a Firestore pipeline, enhancing data manipulation capabilities.
  • Core Implementation: Implemented the Let class in pipeline_stages.py to handle the internal logic and protobuf serialization for the new let stage.
  • Comprehensive Testing: Added both system-level (YAML) and unit tests to validate the functionality, correct argument handling, and protobuf conversion of the let pipeline stage.
Changelog
  • packages/google-cloud-firestore/google/cloud/firestore_v1/base_pipeline.py
    • Added the let method to the _BasePipeline class, allowing users to define variables for subsequent pipeline stages.
  • packages/google-cloud-firestore/google/cloud/firestore_v1/pipeline_stages.py
    • Implemented a new Let class, inheriting from Stage, to represent the 'let' pipeline stage internally.
    • Added _pb_args method to the Let class for converting defined variables into the appropriate protobuf format.
  • packages/google-cloud-firestore/tests/system/pipeline_e2e/general.yaml
    • Included a new system test case (testLetStage) to verify the functionality and correct proto generation of the let pipeline stage.
  • packages/google-cloud-firestore/tests/unit/v1/test_pipeline.py
    • Updated the test_pipeline_methods function to correctly handle keyword arguments for the newly introduced let pipeline stage.
  • packages/google-cloud-firestore/tests/unit/v1/test_pipeline_stages.py
    • Added comprehensive unit tests for the Let class, covering its constructor, string representation (__repr__), and protobuf conversion (_to_pb).
Activity
  • The author has noted two outstanding TODOs: verifying docstrings and adding variable_field_reference, indicating planned follow-up work for this feature.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces support for the let stage in Firestore pipelines, which is a great feature. The implementation looks solid, with new classes for the stage, methods on the pipeline builder, and thorough unit and system tests. I have a couple of suggestions: one to improve the clarity of the docstring for the new let method, and another to ensure deterministic behavior by sorting variables in the Let stage, following repository best practices.

... rating_plus_one=add(Field.of("rating"), 1),
... has_awards=Field.of("awards").exists()
... )
>>> # Later stages can use Variable.of("rating_plus_one")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The docstring mentions Variable.of("rating_plus_one"), but the Variable class or a way to reference variables doesn't seem to be part of this pull request, as indicated by the TODO item add variable_field_reference. To avoid confusion and documenting a feature that is not yet available, it would be better to remove this line. The preceding sentences already explain that variables can be used in subsequent stages.


def __init__(self, **variables: Expression):
super().__init__("let")
self.variables = variables
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

To ensure deterministic output for __repr__ and protobuf serialization, it's a good practice to sort the variables. This aligns with the general principle of producing predictable output, which is especially helpful for testing. You can sort the variables by key when they are assigned in the constructor.

Suggested change
self.variables = variables
self.variables = dict(sorted(variables.items()))
References
  1. To ensure dictionary keys remain sorted without manual effort, programmatically sort the dictionary before returning it (e.g., using dict(sorted(metadata.items()))) instead of relying on manual ordering in the code.

@Linchin Linchin marked this pull request as ready for review March 5, 2026 17:43
@Linchin Linchin requested review from a team as code owners March 5, 2026 17:43
@Linchin
Copy link
Contributor Author

Linchin commented Mar 10, 2026

/gemini review

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

The pull request introduces support for the let stage in Firestore pipelines, allowing users to declare variables that can be referenced in subsequent stages. This includes the addition of a let method to the _BasePipeline class, a new Variable class for referencing these variables, and a Let stage class for processing the variable declarations. The changes are well-tested with both unit and system tests, ensuring correct functionality and protobuf serialization. However, there is a minor inconsistency in the docstring example for the let method regarding how Variable objects are instantiated.

... rating_plus_one=add(Field.of("rating"), 1),
... has_awards=Field.of("awards").exists()
... )
>>> # Later stages can use Variable.of("rating_plus_one")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The example in the docstring suggests using Variable.of("rating_plus_one"), but the Variable class does not have an of class method. It should be instantiated directly as Variable("rating_plus_one").

Suggested change
>>> # Later stages can use Variable.of("rating_plus_one")
>>> # Later stages can use Variable("rating_plus_one")

stages.FindNearest(field, vector, distance_measure, options)
)

def let(self, **variables: Expression) -> "_BasePipeline":
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Drive-by comment, we are using define instead of let for our SDKs(mobile/web/java/node). There is active discussions happening right now on the naming. You probably need to rename it depending on how the discussion goes.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the heads up! Will ping you

@Linchin Linchin added the do not merge Indicates a pull request not ready for merge, due to either quality or timing. label Mar 11, 2026
@Linchin
Copy link
Contributor Author

Linchin commented Mar 11, 2026

Currently blocked by potential renaming per #16030 (comment)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

do not merge Indicates a pull request not ready for merge, due to either quality or timing.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants